Guide: Redirecting Direct HTTPS IP Access to the Server Hostname

1. Objective and Problem

Objective: All HTTPS requests made directly to the server's IP address (e.g., https://1.2.3.4) should be permanently redirected (301) to a fixed, official hostname (e.g., https://srv1.yourdomain.com).

The Problem: Without a specific configuration, Nginx defaults to serving the first available SSL-enabled virtual host for such requests. This results in the certificate and website of an unrelated domain on the server being displayed.

2. The Cause: SNI and the Default Server

When an HTTPS request is made to a hostname (e.g., yourdomain.com), the browser uses SNI (Server Name Indication) to tell the server which website it wants. Nginx can then select the correct server block and the corresponding SSL certificate.

However, when you access the server directly via its IP address (https://1.2.3.4), no hostname is sent via SNI. Nginx is uncertain and defaults to grabbing the first SSL server block it finds in its configuration.

The solution is to create an unambiguous "catch-all" server block that explicitly acts as the default for requests without a hostname.

3. Step-by-Step Solution

  1. Create the Configuration File
    We will create a new configuration file in the /etc/nginx/conf.d/ directory. The 00_ prefix ensures that this file is loaded before any other configurations (like those from VestaCP), giving it priority.
    sudo nano /etc/nginx/conf.d/00_default_https_redirect.conf
  2. Insert the Configuration
    Paste the following code into the newly created file. Remember to replace the placeholders with your actual data.
    # /etc/nginx/conf.d/00_default_https_redirect.conf
    
    server {
        # Listen explicitly on the IP and mark this block as the
        # default fallback for port 443.
        listen YOUR-SERVER-IP:443 ssl default_server;
        http2 on;
    
        # A "catch-all" server_name. The underscore is the convention for this.
        server_name _;
    
        # IMPORTANT: Use the SSL certificate of the TARGET hostname
        # to minimize handshake errors with clients.
        ssl_certificate      /home/admin/conf/web/ssl.YOUR-HOSTNAME.COM.pem;
        ssl_certificate_key  /home/admin/conf/web/ssl.YOUR-HOSTNAME.COM.key;
    
        # Optional log files for debugging
        access_log /var/log/nginx/ip_redirect.log;
        error_log /var/log/nginx/ip_redirect.error.log;
    
        # Perform the permanent 301 redirect to the official hostname.
        # $request_uri preserves the original path and query parameters.
        return 301 https://YOUR-HOSTNAME.COM$request_uri;
    }
  3. Test the Configuration
    Always check the Nginx syntax for errors before reloading the service.
    sudo nginx -t
    The expected output is: syntax is ok and test is successful.
  4. Reload Nginx
    If the test was successful, apply the changes without interrupting the service.
    sudo systemctl reload nginx

4. Verifying the Result

The best way to test the redirect is from the command line using curl.

Important Note on Testing: A normal call to curl https://YOUR-SERVER-IP will fail with an SSL error! This is expected behavior because the certificate is issued for YOUR-HOSTNAME.COM, not for the IP address. We must bypass the certificate validation for this test using the -k flag.

Execute the following command:

curl -I -k https://YOUR-SERVER-IP
Expected Output:
You should see an HTTP/2 301 response, which includes the location header pointing to your target hostname.
HTTP/2 301
server: nginx
date: ...
content-type: text/html
location: https://YOUR-HOSTNAME.COM/
...

In a web browser, visiting the IP address directly will show a security warning. If you click "Advanced" and proceed, the redirect will execute correctly, and you will land on your target domain.


This solution is "update-safe" as it will not be overwritten by VestaCP's configuration changes.